package rtda

import (
	"bytes"
	"encoding/binary"
	"encoding/hex"
	"errors"
	"fmt"
	"math"
	"strconv"
	"strings"

	"github.com/ethereum/go-ethereum/rlp"
	"hundsun.com/hsl/hschain/contract/jvm/jvm.go/rtda/heap"
)

type JavaType struct {
	TypeName string
	Obj      interface{}
}
type CommonParam struct {
	ClassName  string
	MethodName string
	MethodDesc string
	Params     []JavaType
}
type JavaParameter struct {
	FieldObj  JavaType
	FieldName string
}
type DeployPayLoad struct {
	Code        []byte
	ManagerList []string
	JavaParams  []JavaParameter
}

func (thread *Thread) DumpObj(class *heap.Class, obj *heap.Object) string {
	objInfo := "class " + class.Name + ":\n"
	for _, f := range class.Fields {
		fieldName := f.Name
		fieldRef := f.GetValue(obj)
		fieldInfo := "filed name :" + fieldName + ",value: "
		switch f.Descriptor {
		case "V", "B", "Z", "S", "C", "I":
			fieldInfo += strconv.Itoa(int(fieldRef.IntValue()))
		case "J":
			fieldInfo += strconv.Itoa(int(fieldRef.LongValue()))
		case "F":
			floatVal := fieldRef.FloatValue()
			fieldInfo += strconv.FormatFloat(float64(floatVal), 'E', -1, 32)
		case "D":
			doubleVal := fieldRef.DoubleValue()
			fieldInfo += strconv.FormatFloat(doubleVal, 'E', -1, 64)
		case "Ljava/lang/String;":
			fieldInfo += fieldRef.Ref.JSToGoStr()
		case "[B":
			filedBytes := fieldRef.Ref.GetGoBytes()
			fieldInfo += hex.EncodeToString(filedBytes)
		default:
			fieldInfo += "\n"
			fieldInfo += thread.DumpObj(f.Type(), fieldRef.Ref)
		}
		fieldInfo += "\n"
		objInfo += fieldInfo
	}
	fmt.Println(objInfo)
	return objInfo
}
func (thread *Thread) DecodeReferenceObject(getObj *heap.Slot, bytes []byte) (*heap.Slot, error) {
	jlog := thread.Log
	var ref heap.Slot
	var err error
	if getObj.Ref == nil {
		/*var decVal uint64
		err := rlp.DecodeBytes(bytes,&decVal)
		if err != nil {
			return &ref,err
		}
		ref.Val = int64(decVal)*/
		return &ref, nil
	}
	class := getObj.Ref.Class
	switch class.Name {
	case "java/lang/Boolean", "java/lang/Byte":
		var byteVal uint8
		err = rlp.DecodeBytes(bytes, &byteVal)
		if err != nil {
			return nil, err
		}
		jlog.Debugf("esdao get uint8 value %v", byteVal)
		class := thread.Runtime.BootLoader().LoadClass(class.Name)
		byteObj := class.NewObj()
		byteObj.Fields.([]heap.Slot)[0].Val = int64(byteVal)
		ref = heap.NewRefSlot(byteObj)
	case "java/lang/Character", "java/lang/Short":
		var uint16Val uint16
		err = rlp.DecodeBytes(bytes, &uint16Val)
		if err != nil {
			return nil, err
		}
		jlog.Debugf("esdao get uint16 value %v", uint16Val)
		class := thread.Runtime.BootLoader().LoadClass(class.Name)
		shortObj := class.NewObj()
		shortObj.Fields.([]heap.Slot)[0].Val = int64(uint16Val)
		ref = heap.NewRefSlot(shortObj)
	case "java/lang/Integer":
		var intVal uint32
		err = rlp.DecodeBytes(bytes, &intVal)
		if err != nil {
			return nil, err
		}
		jlog.Debugf("esdao get int value %v", intVal)
		class := thread.Runtime.BootLoader().LoadClass("java/lang/Integer")
		intObj := class.NewObj()
		intObj.Fields.([]heap.Slot)[0].Val = int64(intVal)
		ref = heap.NewRefSlot(intObj)
	case "java/lang/Long":
		var longVal uint64
		err = rlp.DecodeBytes(bytes, &longVal)
		jlog.Debugf("esdao get long value %v", longVal)
		if err != nil {
			return nil, err
		}
		class := thread.Runtime.BootLoader().LoadClass("java/lang/Long")
		longObj := class.NewObj()
		longObj.Fields.([]heap.Slot)[0].Val = int64(longVal)
		ref = heap.NewRefSlot(longObj)
	case "java/lang/Float":
		var intVal uint32
		err = rlp.DecodeBytes(bytes, &intVal)
		if err != nil {
			return nil, err
		}
		var floatVal float32
		floatVal = math.Float32frombits(intVal)
		jlog.Debugf("esdao get float value %v", floatVal)
		class := thread.Runtime.BootLoader().LoadClass("java/lang/Float")
		floatObj := class.NewObj()
		floatObj.Fields.([]heap.Slot)[0].Val = int64(intVal)
		ref = heap.NewRefSlot(floatObj)
	case "java/lang/Double":
		var intVal uint64
		err = rlp.DecodeBytes(bytes, &intVal)
		if err != nil {
			return nil, err
		}
		var doubleVal float64
		doubleVal = math.Float64frombits(intVal)
		jlog.Debugf("esdao get double value %v", doubleVal)
		class := thread.Runtime.BootLoader().LoadClass("java/lang/Double")
		doubleObj := class.NewObj()
		doubleObj.Fields.([]heap.Slot)[0].Val = int64(intVal)
		ref = heap.NewRefSlot(doubleObj)
	case "java/lang/String":
		var strVal string
		err = rlp.DecodeBytes(bytes, &strVal)
		if err != nil {
			return nil, err
		}
		jlog.Debugf("esdao get string %s", strVal)
		ref = heap.NewRefSlot(thread.Runtime.JSFromGoStrNoIntern(strVal))
	case "[B", "[Z", "[V":
		var byteArr []byte
		err = rlp.DecodeBytes(bytes, &byteArr)
		if err != nil {
			return nil, err
		}
		jlog.Debugf("esdao get byte array %v", byteArr)
		class := thread.Runtime.BootLoader().LoadClass(class.Name)
		newArr := heap.NewArray(class, uint(len(byteArr)))
		for i, _ := range byteArr {
			newArr.GetBytes()[i] = int8(byteArr[i])
		}
		ref = heap.NewRefSlot(newArr)
	case "[C":
		var charsArr []uint16
		err = rlp.DecodeBytes(bytes, &charsArr)
		if err != nil {
			return nil, err
		}
		jlog.Debugf("esdao get short array %v", charsArr)
		class := thread.Runtime.BootLoader().LoadClass(class.Name)
		newArr := heap.NewArray(class, uint(len(charsArr)))
		for i, _ := range charsArr {
			newArr.GetChars()[i] = charsArr[i]
		}
		ref = heap.NewRefSlot(newArr)
	case "[S":
		var shortsArr []uint16
		err = rlp.DecodeBytes(bytes, &shortsArr)
		if err != nil {
			return nil, err
		}
		jlog.Debugf("esdao get short array %v", shortsArr)
		class := thread.Runtime.BootLoader().LoadClass(class.Name)
		newArr := heap.NewArray(class, uint(len(shortsArr)))
		for i, _ := range shortsArr {
			newArr.GetShorts()[i] = int16(shortsArr[i])
		}
		ref = heap.NewRefSlot(newArr)
	case "[I":
		var intsArr []uint32
		err = rlp.DecodeBytes(bytes, &intsArr)
		if err != nil {
			return nil, err
		}
		jlog.Debugf("esdao get int array %v", intsArr)
		class := thread.Runtime.BootLoader().LoadClass(class.Name)
		newArr := heap.NewArray(class, uint(len(intsArr)))
		for i, _ := range intsArr {
			newArr.GetInts()[i] = int32(intsArr[i])
		}
		ref = heap.NewRefSlot(newArr)
	case "[F":
		var intsArr []uint32
		err = rlp.DecodeBytes(bytes, &intsArr)
		if err != nil {
			return nil, err
		}
		class := thread.Runtime.BootLoader().LoadClass(class.Name)
		newArr := heap.NewArray(class, uint(len(intsArr)))
		for i, _ := range intsArr {
			newArr.GetFloats()[i] = math.Float32frombits(intsArr[i])
		}
		ref = heap.NewRefSlot(newArr)
	case "[J":
		var longsArr []uint64
		err = rlp.DecodeBytes(bytes, &longsArr)
		if err != nil {
			return nil, err
		}
		class := thread.Runtime.BootLoader().LoadClass(class.Name)
		newArr := heap.NewArray(class, uint(len(longsArr)))
		for i, _ := range longsArr {
			newArr.GetLongs()[i] = int64(longsArr[i])
		}
		ref = heap.NewRefSlot(newArr)
	case "[D":
		var longsArr []uint64
		err = rlp.DecodeBytes(bytes, &longsArr)
		if err != nil {
			return nil, err
		}
		class := thread.Runtime.BootLoader().LoadClass(class.Name)
		newArr := heap.NewArray(class, uint(len(longsArr)))
		for i, _ := range longsArr {
			newArr.GetDoubles()[i] = math.Float64frombits(longsArr[i])
		}
		ref = heap.NewRefSlot(newArr)
	case "[Ljava/lang/String;":
		var ifArr []interface{}
		var strArr []string
		err = rlp.DecodeBytes(bytes, &ifArr)
		if err != nil {
			return nil, err
		}
		var str string
		for _, elem := range ifArr {
			err = rlp.DecodeBytes(elem.([]byte), &str)
			if err != nil {
				return nil, err
			}
			strArr = append(strArr, str)
		}
		rt := thread.Runtime
		bl := thread.Runtime.BootLoader()
		class := bl.LoadClass(class.Name)
		newArr := heap.NewArray(class, uint(len(strArr)))
		for i, _ := range strArr {
			newArr.GetRefs()[i] = rt.JSFromGoStrNoIntern(strArr[i])
		}
		ref = heap.NewRefSlot(newArr)
	default:
		if strings.HasPrefix(class.Name, "[L") {
			var ifArr []interface{}
			err = rlp.DecodeBytes(bytes, &ifArr)
			if err != nil {
				return nil, err
			}
			componentClassName := class.Name[2 : len(class.Name)-1]
			componentClass := thread.Runtime.BootLoader().LoadClass(componentClassName)
			if componentClass == nil {
				return nil, errors.New("Decode object array component class " + componentClassName + " not found")
			}
			componentObj := componentClass.NewObj()
			componentSlot := heap.NewRefSlot(componentObj)
			var slots []*heap.Slot
			for _, elem := range ifArr {
				slot, err := thread.DecodeReferenceObject(&componentSlot, elem.([]byte))
				if err != nil {
					return nil, err
				}
				slots = append(slots, slot)
			}
			bl := thread.Runtime.BootLoader()
			class := bl.LoadClass(class.Name)
			newArr := heap.NewArray(class, uint(len(slots)))
			for i, _ := range slots {
				newArr.GetRefs()[i] = slots[i].Ref
			}
			ref = heap.NewRefSlot(newArr)
		} else {
			class := thread.Runtime.BootLoader().LoadClass(class.Name)
			var encBuf []interface{}
			var objBuf [][]byte
			err = rlp.DecodeBytes(bytes, &encBuf)
			for _, buf := range encBuf {
				objBuf = append(objBuf, buf.([]byte))
			}
			obj, err := thread.RlpDecode(class, objBuf)
			if err != nil {
				return nil, err
			}
			//thread.DumpObj(class,obj)
			ref = heap.NewRefSlot(obj)
		}
	}
	return &ref, nil

}
func (thread *Thread) DecodeJavaType(param JavaType) (heap.Slot, error) {
	var err error
	//jlog.Debugf("param [%d] type is %s,obj is %v",i,param.TypeName,param.Obj)
	switch param.TypeName {
	case "boolean", "java.lang.Boolean":
		paramBytes := param.Obj.([]byte)
		bytesBuffer := bytes.NewBuffer(paramBytes)
		var tmp int8
		err := binary.Read(bytesBuffer, binary.BigEndian, &tmp)
		var boolVal int8
		if err == nil {
			boolVal = tmp
		} else {
			return heap.EmptySlot, err
		}
		if param.TypeName == "java.lang.Boolean" {
			class := thread.Runtime.BootLoader().LoadClass("java/lang/Boolean")
			byteObj := class.NewObj()
			byteObj.Fields.([]heap.Slot)[0].Val = int64(boolVal)
			return heap.NewRefSlot(byteObj), nil
		} else {
			return heap.NewIntSlot(int32(boolVal)), nil
		}
		//jlog.Debugf("bool value is %d",boolVal)
	case "char", "java.lang.Character":
		paramBytes := param.Obj.([]byte)
		bytesBuffer := bytes.NewBuffer(paramBytes)
		var tmp uint16
		err := binary.Read(bytesBuffer, binary.BigEndian, &tmp)
		var charVal uint16
		if err == nil {
			charVal = tmp
		} else {
			return heap.EmptySlot, err
		}
		if param.TypeName == "java.lang.Character" {
			class := thread.Runtime.BootLoader().LoadClass("java/lang/Character")
			charObj := class.NewObj()
			charObj.Fields.([]heap.Slot)[0].Val = int64(charVal)
			return heap.NewRefSlot(charObj), nil
		} else {
			return heap.NewIntSlot(int32(charVal)), nil
		}
		//jlog.Debugf("char value is %d",charVal)
	case "byte", "java.lang.Byte":
		paramBytes := param.Obj.([]byte)
		bytesBuffer := bytes.NewBuffer(paramBytes)
		var tmp uint8
		err := binary.Read(bytesBuffer, binary.BigEndian, &tmp)
		var byteVal uint8
		if err == nil {
			byteVal = tmp
		} else {
			return heap.EmptySlot, err
		}
		if param.TypeName == "java.lang.Byte" {
			class := thread.Runtime.BootLoader().LoadClass("java/lang/Byte")
			byteObj := class.NewObj()
			byteObj.Fields.([]heap.Slot)[0].Val = int64(byteVal)
			return heap.NewRefSlot(byteObj), nil
		} else {
			return heap.NewIntSlot(int32(byteVal)), nil
		}
		//jlog.Debugf("byte value is %d",byteVal)
	case "short", "java.lang.Short":
		paramBytes := param.Obj.([]byte)
		bytesBuffer := bytes.NewBuffer(paramBytes)
		var tmp int16
		err := binary.Read(bytesBuffer, binary.BigEndian, &tmp)
		var shortVal int16
		if err == nil {
			shortVal = tmp
		} else {
			return heap.EmptySlot, err
		}
		if param.TypeName == "java.lang.Short" {
			class := thread.Runtime.BootLoader().LoadClass("java/lang/Short")
			shortObj := class.NewObj()
			shortObj.Fields.([]heap.Slot)[0].Val = int64(shortVal)
			return heap.NewRefSlot(shortObj), nil
		} else {
			return heap.NewIntSlot(int32(shortVal)), nil
		}
		//jlog.Debugf("short value is %d",shortVal)
	case "int", "java.lang.Integer":
		paramBytes := param.Obj.([]byte)
		bytesBuffer := bytes.NewBuffer(paramBytes)
		var tmp int32
		err := binary.Read(bytesBuffer, binary.BigEndian, &tmp)
		var intVal int32
		if err == nil {
			intVal = tmp
		} else {
			return heap.EmptySlot, err
		}
		if param.TypeName == "java.lang.Integer" {
			class := thread.Runtime.BootLoader().LoadClass("java/lang/Integer")
			intObj := class.NewObj()
			intObj.Fields.([]heap.Slot)[0].Val = int64(intVal)
			return heap.NewRefSlot(intObj), nil
		} else {
			return heap.NewIntSlot(intVal), nil
		}
		//jlog.Debugf("int value is %d",intVal)
	case "long", "java.lang.Long":
		paramBytes := param.Obj.([]byte)
		bytesBuffer := bytes.NewBuffer(paramBytes)
		var tmp int64
		err := binary.Read(bytesBuffer, binary.BigEndian, &tmp)
		var longVal int64
		if err == nil {
			longVal = tmp
		} else {
			return heap.EmptySlot, err
		}

		if param.TypeName == "java.lang.Long" {
			class := thread.Runtime.BootLoader().LoadClass("java/lang/Long")
			longObj := class.NewObj()
			longObj.Fields.([]heap.Slot)[0].Val = int64(longVal)
			return heap.NewRefSlot(longObj), nil
		} else {
			return heap.NewLongSlot(longVal), nil
		}
		//jlog.Debugf("long value is ",longVal)
	case "float", "java.lang.Float":
		paramBytes := param.Obj.([]byte)
		bytesBuffer := bytes.NewBuffer(paramBytes)
		var tmp int32
		err := binary.Read(bytesBuffer, binary.BigEndian, &tmp)
		var floatVal float32
		if err == nil {
			floatVal = math.Float32frombits(uint32(tmp))
		} else {
			return heap.EmptySlot, err
		}
		if param.TypeName == "java.lang.Float" {
			class := thread.Runtime.BootLoader().LoadClass("java/lang/Float")
			floatObj := class.NewObj()
			floatObj.Fields.([]heap.Slot)[0].Val = int64(tmp)
			return heap.NewRefSlot(floatObj), nil
		} else {
			return heap.NewFloatSlot(floatVal), nil
		}
		//jlog.Debugf("float value is %v",floatVal)
	case "double", "java.lang.Double":
		paramBytes := param.Obj.([]byte)
		bytesBuffer := bytes.NewBuffer(paramBytes)
		var tmp int64
		err := binary.Read(bytesBuffer, binary.BigEndian, &tmp)
		var doubleVal float64
		if err == nil {
			doubleVal = math.Float64frombits(uint64(tmp))
		} else {
			return heap.EmptySlot, err
		}
		if param.TypeName == "java.lang.Double" {
			class := thread.Runtime.BootLoader().LoadClass("java/lang/Double")
			doubleObj := class.NewObj()
			doubleObj.Fields.([]heap.Slot)[0].Val = tmp
			return heap.NewRefSlot(doubleObj), nil
		} else {
			return heap.NewDoubleSlot(doubleVal), nil
		}
		//jlog.Debugf("double value is %v",doubleVal)
	case "java.lang.String":
		paramBytes := param.Obj.([]byte)
		if len(paramBytes) == 0 {
			return heap.EmptySlot, nil
		}
		strVal := string(paramBytes)
		rt := thread.Runtime
		return heap.NewRefSlot(rt.JSFromGoStrNoIntern(strVal)), nil
		//jlog.Debugf("string value is %s",strVal)
	case "[B":
		buff := param.Obj.([]byte)
		class := thread.Runtime.BootLoader().LoadClass(param.TypeName)
		arr := heap.NewArray(class, uint(len(buff)))
		for i := 0; i < len(buff); i++ {
			arr.GetBytes()[i] = int8(buff[i])
		}
		return heap.NewRefSlot(arr), nil
	default:
		var buff []interface{}
		var arr *heap.Object
		buff = param.Obj.([]interface{})
		if strings.HasPrefix(param.TypeName, "[") {
			clsName := strings.Replace(param.TypeName, ".", "/", -1)
			if len(param.TypeName) > len("[Ljava.lang.") {
				wrapperName := clsName[2 : len(clsName)-1]
				if heap.IsPrimitiveWrapperType(wrapperName) {
					clsName = heap.WrapperToArrayClassName(wrapperName)
				}
			}

			class := thread.Runtime.BootLoader().LoadClass(clsName)
			arr = heap.NewArray(class, uint(len(buff)))
			//Primitive array
			if len(clsName) == 2 {
				//class := thread.Runtime.BootLoader().LoadClass(param.TypeName)
				var tmp64 int64
				var tmp32 int32
				var tmp16 int16
				var tmp8 int8
				for i := 0; i < len(buff); i++ {
					bytesBuffer := bytes.NewBuffer(buff[i].([]byte))
					if err == nil {
						switch clsName {
						case "[D":
							err := binary.Read(bytesBuffer, binary.BigEndian, &tmp64)
							if err == nil {
								arr.GetDoubles()[i] = math.Float64frombits(uint64(tmp64))
							}
						case "[J":
							err := binary.Read(bytesBuffer, binary.BigEndian, &tmp64)
							if err == nil {
								arr.GetLongs()[i] = tmp64
							}
						case "[I":
							err := binary.Read(bytesBuffer, binary.BigEndian, &tmp32)
							if err == nil {
								arr.GetInts()[i] = tmp32
							}
						case "[F":
							err := binary.Read(bytesBuffer, binary.BigEndian, &tmp32)
							if err == nil {
								arr.GetFloats()[i] = math.Float32frombits(uint32(tmp32))
							}
						case "[S":
							err := binary.Read(bytesBuffer, binary.BigEndian, &tmp16)
							if err == nil {
								arr.GetShorts()[i] = tmp16
							}
						case "[C":
							err := binary.Read(bytesBuffer, binary.BigEndian, &tmp16)
							if err == nil {
								arr.GetChars()[i] = uint16(tmp16)
							}
						case "[B", "[Z":
							err := binary.Read(bytesBuffer, binary.BigEndian, &tmp8)
							if err == nil {
								arr.GetBytes()[i] = tmp8
							}
						default:
						}
					}
				}
			} else {
				for i := 0; i < len(buff); i++ {
					if clsName == "[Ljava/lang/String;" {
						arr.GetRefs()[i] = thread.Runtime.JSFromGoStrNoIntern(string(buff[i].([]byte)))
					} else {
						componentClass := class.GetComponentClass()
						obj, err := thread.RlpDecode2(componentClass, buff[i].([]interface{}))
						if err == nil {
							arr.GetRefs()[i] = obj
						}
					}
				}
			}
			return heap.NewRefSlot(arr), nil

		} else {
			paramClsName := strings.Replace(param.TypeName, ".", "/", -1)
			class := thread.Runtime.BootLoader().LoadClass(paramClsName)
			if class != nil {
				ref, err := thread.RlpDecode2(class, buff)
				if err != nil {
					//jlog.Errorf("Rlp decode common param object failed,type name %s,error %s", param.TypeName, err.Error())
					return heap.EmptySlot, err
				}
				return heap.NewRefSlot(ref), nil
			}
		}
	}
	return heap.EmptySlot, nil
}
func (thread *Thread) DecodeCommonParam(paramBytes []byte) (*CommonParam, []heap.Slot, error) {
	jlog := thread.Log
	if paramBytes == nil {
		return nil, nil, nil
	}
	var commonParam CommonParam
	err := rlp.DecodeBytes(paramBytes, &commonParam)
	//fmt.Println("Encode result is ",hex.EncodeToString(testBytes))
	if err != nil {
		jlog.Errorf("Decode common parameters bytes to list failed %s", err.Error())
		return nil, nil, err
	}

	//parameter list
	var methodArgs []heap.Slot
	for _, param := range commonParam.Params {
		if param.TypeName == "java.util.HashMap" {
			var buff []interface{}
			buff = param.Obj.([]interface{})
			slot, err := thread.RlpDecodeMap(buff)
			if err == nil {
				methodArgs = append(methodArgs, slot)
			}
		} else if param.TypeName == "java.util.ArrayList" {
			var buff []interface{}
			buff = param.Obj.([]interface{})
			slot, err := thread.RlpDecodeList(buff)
			if err == nil {
				methodArgs = append(methodArgs, slot)
			}
		} else {
			javaType, err := thread.DecodeJavaType(param)
			if err != nil {
				return nil, nil, err
			}
			methodArgs = append(methodArgs, javaType)
		}
	}
	return &commonParam, methodArgs, nil
}
func (thread *Thread) DecodeDepolyInitParam(param JavaType) (heap.Slot, error) {
	jlog := thread.Log
	//parameter init object
	obj, err := thread.DecodeJavaType(param)
	if err != nil {
		jlog.Errorf("Decode deploy init parameters javatype failed %s", err.Error())
		return heap.EmptySlot, err
	}

	return obj, nil
}
func (thread *Thread) RlpDecode(class *heap.Class, buff [][]byte) (*heap.Object, error) {
	if len(buff) != len(class.Fields) {
		panic("buff size must be same as the class fileds number")
	}
	ref := class.NewObj()
	var err error
	for i, f := range class.Fields {
		switch f.Descriptor {
		case "Z", "V", "B":
			var byteVal uint8
			err = rlp.DecodeBytes(buff[i], &byteVal)
			if err != nil {
				return nil, err
			}
			ref.SetFieldValue(f.Name, f.Descriptor, heap.NewIntSlot(int32(byteVal)))
		case "C":
			var charVal uint16
			err = rlp.DecodeBytes(buff[i], &charVal)
			if err != nil {
				return nil, err
			}
			ref.SetFieldValue(f.Name, f.Descriptor, heap.NewIntSlot(int32(charVal)))
		case "S":
			var shortVal uint16
			err = rlp.DecodeBytes(buff[i], &shortVal)
			if err != nil {
				return nil, err
			}
			ref.SetFieldValue(f.Name, f.Descriptor, heap.NewIntSlot(int32(shortVal)))
		case "I", "F":
			var int32Val uint32
			err = rlp.DecodeBytes(buff[i], &int32Val)
			if err != nil {
				return nil, err
			}
			ref.SetFieldValue(f.Name, f.Descriptor, heap.NewIntSlot(int32(int32Val)))
		case "J", "D":
			var int64Val uint64
			err = rlp.DecodeBytes(buff[i], &int64Val)
			if err != nil {
				return nil, err
			}
			ref.SetFieldValue(f.Name, f.Descriptor, heap.NewLongSlot(int64(int64Val)))
		case "Ljava/lang/Byte;", "Ljava/lang/Boolean;", "Ljava/lang/Character;", "Ljava/lang/Short;",
			"Ljava/lang/Integer;", "Ljava/lang/Long;", "Ljava/lang/Float;", "Ljava/lang/Double;":
			var val int64
			var valInt8 uint8
			var valInt16 uint16
			var valInt32 uint32
			var valInt64 uint64
			if f.Descriptor == "Ljava/lang/Byte;" || f.Descriptor == "Ljava/lang/Boolean;" {
				err = rlp.DecodeBytes(buff[i], &valInt8)
				val = int64(valInt8)
			} else if f.Descriptor == "Ljava/lang/Character;" || f.Descriptor == "Ljava/lang/Short;" {
				err = rlp.DecodeBytes(buff[i], &valInt16)
				val = int64(valInt16)
			} else if f.Descriptor == "Ljava/lang/Integer;" || f.Descriptor == "Ljava/lang/Float;" {
				err = rlp.DecodeBytes(buff[i], &valInt32)
				val = int64(valInt32)
			} else if f.Descriptor == "Ljava/lang/Long;" || f.Descriptor == "Ljava/lang/Double;" {
				err = rlp.DecodeBytes(buff[i], &valInt64)
				val = int64(valInt64)
			}
			if err != nil {
				return nil, err
			}
			rt := thread.Runtime
			fieldClass := rt.BootLoader().LoadClass(f.Descriptor[1 : len(f.Descriptor)-1])
			obj := fieldClass.NewObj()
			obj.Fields.([]heap.Slot)[0].Val = val
			ref.SetFieldValue(f.Name, f.Descriptor, heap.NewRefSlot(obj))
		case "Ljava/lang/String;":
			var strVal string
			err = rlp.DecodeBytes(buff[i], &strVal)
			if err != nil {
				fmt.Println("RlpDecode decode string field error ", err.Error())
				return nil, err
			}
			rt := thread.Runtime
			ref.SetFieldValue(f.Name, f.Descriptor, heap.NewRefSlot(rt.JSFromGoStrNoIntern(strVal)))
		case "[B", "[Z":
			var arrVal []byte
			err = rlp.DecodeBytes(buff[i], &arrVal)
			if err != nil {
				return nil, err
			}
			class := thread.Runtime.BootLoader().LoadClass(f.Descriptor)
			arr := heap.NewArray(class, uint(len(arrVal)))
			for i := 0; i < len(arrVal); i++ {
				arr.GetBytes()[i] = int8(arrVal[i])
			}
			ref.SetFieldValue(f.Name, f.Descriptor, heap.NewRefSlot(arr))
		case "[C", "[S", "[I", "[J", "[F", "[D":
			var arrVal []interface{}
			var int16Val uint16
			var int32Val uint32
			var int64Val uint64
			class := thread.Runtime.BootLoader().LoadClass(f.Descriptor)
			err = rlp.DecodeBytes(buff[i], &arrVal)
			if err != nil {
				return nil, err
			}
			arr := heap.NewArray(class, uint(len(arrVal)))
			for i, _ := range arrVal {
				if f.Descriptor == "[S" || f.Descriptor == "[C" {
					err = rlp.DecodeBytes(arrVal[i].([]byte), &int16Val)
					if err == nil {
						if f.Descriptor == "[S" {
							arr.GetChars()[i] = int16Val
						} else {
							arr.GetShorts()[i] = int16(int16Val)
						}
					}
				} else if f.Descriptor == "[I" || f.Descriptor == "[F" {
					err = rlp.DecodeBytes(arrVal[i].([]byte), &int32Val)
					if err == nil {
						if f.Descriptor == "[I" {
							arr.GetInts()[i] = int32(int32Val)
						} else {
							arr.GetFloats()[i] = math.Float32frombits(int32Val)
						}
					}
				} else {
					err = rlp.DecodeBytes(arrVal[i].([]byte), &int64Val)
					if err == nil {
						if f.Descriptor == "[J" {
							arr.GetLongs()[i] = int64(int64Val)
						} else {
							arr.GetDoubles()[i] = math.Float64frombits(int64Val)
						}
					}
				}
				if err != nil {
					return nil, err
				}
			}
			ref.SetFieldValue(f.Name, f.Descriptor, heap.NewRefSlot(arr))
		case "[Ljava/lang/Byte;", "[Ljava/lang/Boolean;", "[Ljava/lang/Character;", "[Ljava/lang/Short;",
			"[Ljava/lang/Integer;", "[Ljava/lang/Float;", "[Ljava/lang/Long;", "[Ljava/lang/Double;":
			var arrVal []interface{}
			err = rlp.DecodeBytes(buff[i], &arrVal)
			if err != nil {
				return nil, err
			}
			arrLen := len(arrVal)
			arrClass := thread.Runtime.BootLoader().LoadClass(f.Descriptor)
			compentClass := arrClass.GetComponentClass()
			arr := heap.NewArray(arrClass, uint(arrLen))
			var val int64
			var int8Val uint8
			var int16Val uint16
			var int32Val uint32
			var int64Val uint64
			for i := 0; i < arrLen; i++ {
				compentObj := compentClass.NewObj()
				if f.Descriptor == "[Ljava/lang/Byte;" || f.Descriptor == "[Ljava/lang/Boolean;" {
					err = rlp.DecodeBytes(arrVal[i].([]byte), &int8Val)
					val = int64(int8Val)
				} else if f.Descriptor == "[Ljava/lang/Character;" || f.Descriptor == "[Ljava/lang/Short;" {
					err = rlp.DecodeBytes(arrVal[i].([]byte), &int16Val)
					val = int64(int16Val)
				} else if f.Descriptor == "[Ljava/lang/Integer;" || f.Descriptor == "[Ljava/lang/Float;" {
					err = rlp.DecodeBytes(arrVal[i].([]byte), &int32Val)
					val = int64(int32Val)
				} else {
					err = rlp.DecodeBytes(arrVal[i].([]byte), &int64Val)
					val = int64(int64Val)
				}
				if err != nil {
					return nil, err
				}
				compentObj.Fields.([]heap.Slot)[0].Val = val
				arr.GetRefs()[i] = compentObj
			}
			ref.SetFieldValue(f.Name, f.Descriptor, heap.NewRefSlot(arr))
		case "[Ljava/lang/String;":
			var arrVal []interface{}
			err = rlp.DecodeBytes(buff[i], &arrVal)
			if err != nil {
				return nil, err
			}
			arrLen := len(arrVal)
			arrClass := thread.Runtime.BootLoader().LoadClass(f.Descriptor)
			arr := heap.NewArray(arrClass, uint(arrLen))
			var val string
			for i := 0; i < arrLen; i++ {
				err = rlp.DecodeBytes(arrVal[i].([]byte), &val)
				if err != nil {
					return nil, err
				}
				arr.GetRefs()[i] = thread.Runtime.JSFromGoStrNoIntern(val)
			}
			ref.SetFieldValue(f.Name, f.Descriptor, heap.NewRefSlot(arr))
		default:
			if strings.HasPrefix(f.Descriptor, "[") {
				panic("Not support reference array")
			}
			//引用类型
			var decodeBuff []interface{}
			err := rlp.DecodeBytes(buff[i], &decodeBuff)
			if err != nil {
				fmt.Println(err.Error())
				return nil, err
			}
			var fieldBuff [][]byte
			for i := 0; i < len(decodeBuff); i++ {
				fieldBuff = append(fieldBuff, decodeBuff[i].([]byte))
			}
			fieldRef, err := thread.RlpDecode(f.Type(), fieldBuff)
			if err != nil {
				return nil, err
			}
			ref.SetFieldValue(f.Name, f.Descriptor, heap.NewRefSlot(fieldRef))
		}
	}
	return ref, nil
}
func (thread *Thread) RlpDecodeMap(buff []interface{}) (heap.Slot, error) {
	if len(buff) < 2 {
		return heap.EmptySlot, nil
	}
	keyClassName := string(buff[0].([]byte))
	valueClassName := string(buff[1].([]byte))
	//keyClass := thread.Runtime.BootLoader().LoadClass(keyClassName)
	//valueClass := thread.Runtime.BootLoader().LoadClass(valueClassName)
	fmt.Printf("RlpDecodeMap key class is %s,value class is %s\n", keyClassName, valueClassName)
	var mapElemArry []heap.Slot
	for i := 2; i < len(buff); i++ {
		typeName := keyClassName
		if i%2 != 0 {
			typeName = valueClassName
		}
		if typeName == "java.util.HashMap" {
			if buffIfs, ok := buff[i].([]interface{}); ok {
				slot, err := thread.RlpDecodeMap(buffIfs)
				if err == nil {
					mapElemArry = append(mapElemArry, slot)
				}
			} else {
				return heap.EmptySlot, nil
			}
		} else if typeName == "java.util.ArrayList" {
			if buffIfs, ok := buff[i].([]interface{}); ok {
				thread.RlpDecodeList(buffIfs)
			} else {
				return heap.EmptySlot, nil
			}
		} else {
			javaType := JavaType{TypeName: typeName, Obj: buff[i]}
			slot, err := thread.DecodeJavaType(javaType)
			if err == nil {
				mapElemArry = append(mapElemArry, slot)
			}
		}
	}
	class := thread.Runtime.BootLoader().LoadClass("java/util/HashMap")
	obj := &heap.Object{
		Class:   class,
		Fields:  mapElemArry,
		Extra:   nil,
		Monitor: nil,
	}
	return heap.NewRefSlot(obj), nil

}
func (thread *Thread) RlpDecodeList(buff []interface{}) (heap.Slot, error) {
	if len(buff) < 1 {
		return heap.EmptySlot, nil
	}
	elemClassName := string(buff[0].([]byte))
	fmt.Printf("RlpDecodeList element class is %s\n", elemClassName)
	var listElemArry []heap.Slot
	for i := 1; i < len(buff); i++ {
		if elemClassName == "java.util.HashMap" {
			if buffIfs, ok := buff[i].([]interface{}); ok {
				slot, err := thread.RlpDecodeMap(buffIfs)
				if err == nil {
					listElemArry = append(listElemArry, slot)
				}
			} else {
				return heap.EmptySlot, nil
			}
		} else if elemClassName == "java.util.ArrayList" {
			if buffIfs, ok := buff[i].([]interface{}); ok {
				slot, err := thread.RlpDecodeList(buffIfs)
				if err == nil {
					listElemArry = append(listElemArry, slot)
				}
			} else {
				return heap.EmptySlot, nil
			}
		} else {
			javaType := JavaType{TypeName: elemClassName, Obj: buff[i]}
			slot, err := thread.DecodeJavaType(javaType)
			if err == nil {
				listElemArry = append(listElemArry, slot)
			}
		}
	}
	class := thread.Runtime.BootLoader().LoadClass("java/util/ArrayList")
	obj := &heap.Object{
		Class:   class,
		Fields:  listElemArry,
		Extra:   nil,
		Monitor: nil,
	}
	return heap.NewRefSlot(obj), nil

}
func (thread *Thread) RlpDecode2(class *heap.Class, buff []interface{}) (*heap.Object, error) {
	if buff == nil {
		panic("RlpDecode2 buff is nil")
	}

	if class.Name == "java/util/HashMap" || class.Name == "java/util/ArrayList" {
	} else if len(buff) != len(class.Fields) {
		panic("buff size must be same as the class fileds number")
	}
	ref := class.NewObj()
	var err error
	for i, f := range class.Fields {
		if buff[i] == nil {
			continue
		}
		switch f.Descriptor {
		case "Z", "V", "B":
			var byteVal uint8
			bytesBuffer := bytes.NewBuffer(buff[i].([]byte))
			var tmp int8
			err := binary.Read(bytesBuffer, binary.BigEndian, &tmp)
			if err == nil {
				byteVal = uint8(tmp)
			}
			ref.SetFieldValue(f.Name, f.Descriptor, heap.NewIntSlot(int32(byteVal)))
		case "C":
			var charVal uint16
			bytesBuffer := bytes.NewBuffer(buff[i].([]byte))
			var tmp uint16
			err := binary.Read(bytesBuffer, binary.BigEndian, &tmp)
			if err == nil {
				charVal = tmp
			}
			ref.SetFieldValue(f.Name, f.Descriptor, heap.NewIntSlot(int32(charVal)))
		case "S":
			var shortVal int16
			bytesBuffer := bytes.NewBuffer(buff[i].([]byte))
			var tmp int16
			err := binary.Read(bytesBuffer, binary.BigEndian, &tmp)
			if err == nil {
				shortVal = tmp
			}
			ref.SetFieldValue(f.Name, f.Descriptor, heap.NewIntSlot(int32(shortVal)))
		case "I", "F":
			var int32Val int32
			bytesBuffer := bytes.NewBuffer(buff[i].([]byte))
			var tmp int32
			err := binary.Read(bytesBuffer, binary.BigEndian, &tmp)
			if err == nil {
				int32Val = tmp
			}
			ref.SetFieldValue(f.Name, f.Descriptor, heap.NewIntSlot(int32Val))
		case "J", "D":
			var int64Val int64
			bytesBuffer := bytes.NewBuffer(buff[i].([]byte))
			var tmp int64
			err := binary.Read(bytesBuffer, binary.BigEndian, &tmp)
			if err == nil {
				int64Val = tmp
			}
			ref.SetFieldValue(f.Name, f.Descriptor, heap.NewLongSlot(int64Val))
		case "Ljava/lang/Byte;", "Ljava/lang/Boolean;", "Ljava/lang/Character;", "Ljava/lang/Short;",
			"Ljava/lang/Integer;", "Ljava/lang/Long;", "Ljava/lang/Float;", "Ljava/lang/Double;":
			var val int64
			var valInt8 uint8
			var valInt16 uint16
			var valInt32 uint32
			var valInt64 uint64
			if len(buff[i].([]byte)) > 0 {
				bytesBuffer := bytes.NewBuffer(buff[i].([]byte))
				if f.Descriptor == "Ljava/lang/Byte;" || f.Descriptor == "Ljava/lang/Boolean;" {
					err = binary.Read(bytesBuffer, binary.BigEndian, &valInt8)
					val = int64(valInt8)
				} else if f.Descriptor == "Ljava/lang/Character;" || f.Descriptor == "Ljava/lang/Short;" {
					err = binary.Read(bytesBuffer, binary.BigEndian, &valInt16)
					val = int64(valInt16)
				} else if f.Descriptor == "Ljava/lang/Integer;" || f.Descriptor == "Ljava/lang/Float;" {
					err = binary.Read(bytesBuffer, binary.BigEndian, &valInt32)
					val = int64(valInt32)
				} else if f.Descriptor == "Ljava/lang/Long;" || f.Descriptor == "Ljava/lang/Double;" {
					err = binary.Read(bytesBuffer, binary.BigEndian, &valInt64)
					val = int64(valInt64)
				}
				if err != nil {
					return nil, err
				}
			}
			rt := thread.Runtime
			fieldClass := rt.BootLoader().LoadClass(f.Descriptor[1 : len(f.Descriptor)-1])
			obj := fieldClass.NewObj()
			obj.Fields.([]heap.Slot)[0].Val = val
			ref.SetFieldValue(f.Name, f.Descriptor, heap.NewRefSlot(obj))
		case "Ljava/lang/String;":
			var strVal string
			strVal = string(buff[i].([]byte))
			rt := thread.Runtime
			ref.SetFieldValue(f.Name, f.Descriptor, heap.NewRefSlot(rt.JSFromGoStrNoIntern(strVal)))
		case "[B", "[Z", "[V":
			var bytesVal []byte
			if len(buff[i].([]byte)) > 0 {
				bytesVal = buff[i].([]byte)
				class := thread.Runtime.BootLoader().LoadClass(f.Descriptor)
				arr := heap.NewArray(class, uint(len(bytesVal)))
				for i, _ := range bytesVal {
					arr.GetBytes()[i] = int8(bytesVal[i])
				}
				ref.SetFieldValue(f.Name, f.Descriptor, heap.NewRefSlot(arr))
			}
		case "[C", "[S", "[I", "[J", "[F", "[D":
			arrVal, ok := buff[i].([]interface{})
			if ok && len(arrVal) > 0 {
				class := thread.Runtime.BootLoader().LoadClass(f.Descriptor)
				arr := heap.NewArray(class, uint(len(arrVal)))
				var valInt16 uint16
				var valInt32 uint32
				var valInt64 uint64
				for i, _ := range arrVal {
					bytesBuffer := bytes.NewBuffer(arrVal[i].([]byte))
					if f.Descriptor == "[C" || f.Descriptor == "[S" {
						err = binary.Read(bytesBuffer, binary.BigEndian, &valInt16)
						if err == nil {
							if f.Descriptor == "[S" {
								arr.GetShorts()[i] = int16(valInt16)
							} else {
								arr.GetChars()[i] = valInt16
							}
						}
					} else if f.Descriptor == "[I" || f.Descriptor == "[F" {
						err = binary.Read(bytesBuffer, binary.BigEndian, &valInt32)
						if err == nil {
							if f.Descriptor == "[I" {
								arr.GetInts()[i] = int32(valInt32)
							} else {
								arr.GetFloats()[i] = math.Float32frombits(valInt32)
							}
						}
					} else {
						err = binary.Read(bytesBuffer, binary.BigEndian, &valInt64)
						if err == nil {
							if f.Descriptor == "[J" {
								arr.GetLongs()[i] = int64(valInt64)
							} else {
								arr.GetDoubles()[i] = math.Float64frombits(valInt64)
							}
						}
					}
				}
				if err != nil {
					return nil, err
				}
				ref.SetFieldValue(f.Name, f.Descriptor, heap.NewRefSlot(arr))

			} else {
				ref.SetFieldValue(f.Name, f.Descriptor, heap.EmptySlot)
			}
		case "[Ljava/lang/Byte;", "[Ljava/lang/Boolean;", "[Ljava/lang/Character;", "[Ljava/lang/Short;",
			"[Ljava/lang/Integer;", "[Ljava/lang/Float;", "[Ljava/lang/Long;", "[Ljava/lang/Double;":
			arrVal, ok := buff[i].([]interface{})
			if ok {
				arrLen := len(arrVal)
				arrClass := thread.Runtime.BootLoader().LoadClass(f.Descriptor)
				compentClass := arrClass.GetComponentClass()
				arr := heap.NewArray(arrClass, uint(arrLen))
				var val int64
				var int8Val uint8
				var int16Val uint16
				var int32Val uint32
				var int64Val uint64
				for i := 0; i < arrLen; i++ {
					compentObj := compentClass.NewObj()
					bytesBuffer := bytes.NewBuffer(arrVal[i].([]byte))
					if f.Descriptor == "[Ljava/lang/Byte;" || f.Descriptor == "[Ljava/lang/Boolean;" {
						err = binary.Read(bytesBuffer, binary.BigEndian, &int8Val)
						val = int64(int8Val)
					} else if f.Descriptor == "[Ljava/lang/Character;" || f.Descriptor == "[Ljava/lang/Short;" {
						err = binary.Read(bytesBuffer, binary.BigEndian, &int16Val)
						val = int64(int16Val)
					} else if f.Descriptor == "[Ljava/lang/Integer;" || f.Descriptor == "[Ljava/lang/Float;" {
						err = binary.Read(bytesBuffer, binary.BigEndian, &int32Val)
						val = int64(int32Val)
					} else {
						err = binary.Read(bytesBuffer, binary.BigEndian, &int64Val)
						val = int64(int64Val)
					}
					if err != nil {
						return nil, err
					}
					compentObj.Fields.([]heap.Slot)[0].Val = val
					arr.GetRefs()[i] = compentObj
				}
				ref.SetFieldValue(f.Name, f.Descriptor, heap.NewRefSlot(arr))
			} else {
				ref.SetFieldValue(f.Name, f.Descriptor, heap.EmptySlot)
			}
		case "[Ljava/lang/String;":
			arrVal, ok := buff[i].([]interface{})
			if ok {
				arrLen := len(arrVal)
				arrClass := thread.Runtime.BootLoader().LoadClass(f.Descriptor)
				arr := heap.NewArray(arrClass, uint(arrLen))
				for i := 0; i < arrLen; i++ {
					arr.GetRefs()[i] = thread.Runtime.JSFromGoStrNoIntern(string(arrVal[i].([]byte)))
				}
				ref.SetFieldValue(f.Name, f.Descriptor, heap.NewRefSlot(arr))
			} else {
				ref.SetFieldValue(f.Name, f.Descriptor, heap.EmptySlot)
			}
		default:
			if strings.HasPrefix(f.Descriptor, "[") {
				panic("Not support reference array")
			}
			//引用类型
			if fieldBuff, ok := buff[i].([]interface{}); ok {
				if len(fieldBuff) > 0 {
					fieldRef, err := thread.RlpDecode2(f.Type(), fieldBuff)
					if err != nil {
						return nil, err
					}
					ref.SetFieldValue(f.Name, f.Descriptor, heap.NewRefSlot(fieldRef))
				}
			} else {
				ref.SetFieldValue(f.Name, f.Descriptor, heap.EmptySlot)
			}
		}
	}
	return ref, nil
}
func (thread *Thread) RlpEncode(slot *heap.Slot, desc string) ([]byte, error) {
	var putBytes []byte
	var err error
	if slot.Ref == nil && desc != "" {
		switch desc {
		case "Z", "B", "byte", "boolean":
			var bi uint8
			bi = uint8(slot.IntValue())
			return rlp.EncodeToBytes(bi)
		case "C", "S", "char", "short":
			var ci uint16
			ci = uint16(slot.IntValue())
			return rlp.EncodeToBytes(ci)
		case "I", "F", "int", "float":
			return rlp.EncodeToBytes(uint32(slot.IntValue()))
		case "J", "D", "long", "double":
			return rlp.EncodeToBytes(uint64(slot.LongValue()))
		default:
			//ref nil
			var emptyBytes []byte
			return rlp.EncodeToBytes(emptyBytes)
		}
	}
	obj := slot.Ref
	if obj == nil {
		var eb []byte
		return rlp.EncodeToBytes(eb)
	}
	class := thread.Runtime.BootLoader().LoadClass(obj.Class.Name)
	if class == nil {
		return nil, errors.New("not found class")
	}

	switch class.Name {
	case "java/lang/Boolean", "java/lang/Byte":
		uint8Val := uint8(obj.Fields.([]heap.Slot)[0].Val)
		putBytes, err = rlp.EncodeToBytes(uint8Val)
	case "java/lang/Character", "java/lang/Short":
		uint16Val := uint16(obj.Fields.([]heap.Slot)[0].Val)
		putBytes, err = rlp.EncodeToBytes(uint16Val)
	case "java/lang/Integer", "java/lang/Float":
		putBytes, err = rlp.EncodeToBytes(uint32(obj.Fields.([]heap.Slot)[0].Val))
	case "java/lang/Long", "java/lang/Double":
		putBytes, err = rlp.EncodeToBytes(uint64(obj.Fields.([]heap.Slot)[0].Val))
	case "java/lang/String":
		putBytes, err = rlp.EncodeToBytes(obj.JSToGoStr())
	case "[B", "[Z", "[V":
		putBytes, err = rlp.EncodeToBytes(obj.GetGoBytes())
	case "[C", "[S":
		intArr := obj.GetInts()
		var arrBytes [][]byte
		for i, _ := range intArr {
			encBytes, err := rlp.EncodeToBytes(uint16(intArr[i]))
			if err == nil {
				arrBytes = append(arrBytes, encBytes)
			}
		}
		putBytes, err = rlp.EncodeToBytes(arrBytes)
	case "[I":
		intArr := obj.GetInts()
		var arrBytes [][]byte
		for i, _ := range intArr {
			encBytes, err := rlp.EncodeToBytes(uint32(intArr[i]))
			if err == nil {
				arrBytes = append(arrBytes, encBytes)
			}
		}
		putBytes, err = rlp.EncodeToBytes(arrBytes)
	case "[F":
		floatArr := obj.GetFloats()
		var arrBytes [][]byte
		for i, _ := range floatArr {
			encBytes, err := rlp.EncodeToBytes(math.Float32bits(floatArr[i]))
			if err == nil {
				arrBytes = append(arrBytes, encBytes)
			}
		}
		putBytes, err = rlp.EncodeToBytes(arrBytes)
	case "[J":
		longArr := obj.GetLongs()
		var arrBytes [][]byte
		for i, _ := range longArr {
			encBytes, err := rlp.EncodeToBytes(uint64(longArr[i]))
			if err == nil {
				arrBytes = append(arrBytes, encBytes)
			}
		}
		putBytes, err = rlp.EncodeToBytes(arrBytes)
	case "[D":
		doubleArr := obj.GetDoubles()
		var arrBytes [][]byte
		for i, _ := range doubleArr {
			encBytes, err := rlp.EncodeToBytes(math.Float64bits(doubleArr[i]))
			if err == nil {
				arrBytes = append(arrBytes, encBytes)
			}
		}
		putBytes, err = rlp.EncodeToBytes(arrBytes)
	case "[Ljava/lang/Byte;", "[Ljava/lang/Boolean;", "[Ljava/lang/Character;", "[Ljava/lang/Short;",
		"[Ljava/lang/Integer;", "[Ljava/lang/Long;", "[Ljava/lang/Float;", "[Ljava/lang/Double;":
		refArr := obj.GetRefs()
		var arrBytes [][]byte
		var encBytes []byte
		var err error
		for i, _ := range refArr {
			val := refArr[i].Fields.([]heap.Slot)[0].Val
			if class.Name == "[Ljava/lang/Byte;" || class.Name == "[Ljava/lang/Boolean;" {
				encBytes, err = rlp.EncodeToBytes(uint8(val))
			} else if class.Name == "[Ljava/lang/Character;" || class.Name == "[Ljava/lang/Short;" {
				encBytes, err = rlp.EncodeToBytes(uint16(val))
			} else if class.Name == "[Ljava/lang/Integer;" || class.Name == "[Ljava/lang/Float;" {
				encBytes, err = rlp.EncodeToBytes(uint32(val))
			} else {
				encBytes, err = rlp.EncodeToBytes(uint64(val))
			}
			if err == nil {
				arrBytes = append(arrBytes, encBytes)
			}
		}
		putBytes, err = rlp.EncodeToBytes(arrBytes)
	case "[Ljava/lang/String;":
		refArr := obj.GetRefs()
		strArr := make([]string, len(refArr))
		var arrBytes [][]byte
		for i, _ := range refArr {
			strArr[i] = refArr[i].JSToGoStr()
			encBytes, err := rlp.EncodeToBytes(strArr[i])
			if err == nil {
				arrBytes = append(arrBytes, encBytes)
			}
		}
		putBytes, err = rlp.EncodeToBytes(arrBytes)
	default:
		if strings.HasPrefix(class.Name, "[L") {
			refArr := obj.GetRefs()
			var arrBytes [][]byte
			for i, _ := range refArr {
				slot := heap.NewRefSlot(refArr[i])
				componentBytes, err := thread.RlpEncode(&slot, "")
				if err != nil {
					fmt.Printf("RlpEncode array class %s component %d failed ,err %s\n", class.Name, i, err.Error())
				}
				arrBytes = append(arrBytes, componentBytes)
			}
			putBytes, err = rlp.EncodeToBytes(arrBytes)
		} else {
			//合约对象
			var oBytes [][]byte
			for _, f := range class.Fields {
				fieldObj := obj.GetFieldValue(f.Name, f.Descriptor)
				fBytes, err := thread.RlpEncode(&fieldObj, f.Descriptor)
				if err != nil {
					fmt.Printf("RlpEncode class %s field %s failed ,err %s\n", class.Name, f.Name, err.Error())
				}
				oBytes = append(oBytes, fBytes)
			}
			putBytes, err = rlp.EncodeToBytes(oBytes)
		}
	}
	if err != nil {
		fmt.Println("RlpEncode failed,err " + err.Error())
	}
	return putBytes, err
}
